import 'package:lib_bt/send/PackageInterface.dart';
import 'package:lib_util/ByteUtils.dart';
import 'package:lib_util/CrcUtils.dart';
import 'package:ileddemo/code/ble/protocol/base/RectConverter.dart';
import 'package:ileddemo/code/ble/protocol/base/SizeConverter.dart';
import 'package:ileddemo/code/ble/protocol/base/SourceType.dart';
import 'package:flutter/material.dart';
import 'dart:typed_data';
import 'package:json_annotation/json_annotation.dart';
import 'package:image/image.dart' as img;
import 'dart:ui' as ui;
import 'package:lib_util/FileUtil.dart';

import '../../../../util/ColorUtil.dart';
import '../ColorSourceInterface.dart';
import '../partition/PartitionSourceBean.dart';

part 'GraffitiSourceBean.g.dart';

@JsonSerializable()
class GraffitiSourceBean extends ColorSourceInterface {
  //图片文件路径
  String imagePath = "";

  //图片数据
  @JsonKey(ignore: true)
  Uint8List? imgData;

  void setImagePath(String path) {
    imagePath = path;
    imgData = null;
    imgData = getBytes();
    _memoryImage = MemoryImage(imgData!);
    notifyListeners();
  }

  @JsonKey(ignore: true)
  MemoryImage? _memoryImage;

  @JsonKey(ignore: true)
  MemoryImage get memoryImage {
    _memoryImage ??= MemoryImage(getBytes());
    return _memoryImage!;
  }

  GraffitiSourceBean() {
    sourceType = SourceType.TYPE_GRAFFITI;
  }

  GraffitiSourceBean.formImage(img.Image image) {
    sourceType = SourceType.TYPE_GRAFFITI;
    imgData = img.encodePng(image);
    screenSize = Size(image.width.toDouble(), image.height.toDouble());
  }

  factory GraffitiSourceBean.fromJson(Map<String, dynamic> json) => _$GraffitiSourceBeanFromJson(json);

  @override
  Map<String, dynamic> toJson() => _$GraffitiSourceBeanToJson(this);

  Uint8List getBytes() {
    imgData ??= FileUtil.readFile(imagePath);
    return imgData!;
  }

  img.Image? getImage() {
    return img.decodeImage(getBytes());
  }

  Future<ui.Image?> getUiImage()async{
    final ui.Codec codec = await ui.instantiateImageCodec(getBytes());
    final ui.FrameInfo frameInfo = await codec.getNextFrame();
    return frameInfo.image;
  }

  @override
  Future<List<int>> getSendData(bleBean) async {
    const List<int> byteList = [0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01];
    List<int> data = [];
    var image = getImage();
    if (image == null) {
      print("图片读取失败");
      return data;
    }
    Color getColor(int x, int y) {
      var color = image.getPixel(x, y);
      return Color.fromRGBO(color.r.toInt(), color.g.toInt(), color.b.toInt(), 255);
    }

    if (bleBean.screenColorType == 1) {
      ///单色屏 无驱动
      // 计算平均灰度值
      final avgGray = getAvgGray(image);

      int sum = 0;
      int count = 0;
      int index = 0;
      for (int x = 0; x < screenSize.width.toInt(); x++) {
        for (int y = 0; y < screenSize.height.toInt(); y++) {
          //8个合并为一个字节
          if (count != 0 && count % byteList.length == 0) {
            data.add(sum);
            count = 0;
            sum = 0;
          }

          if (index != 0 && index % screenSize.height.toInt() == 0) {
            data.add(sum);
            count = 0;
            sum = 0;
          }

          var color = getColor(x, y);
          if (color != Colors.black && color != Colors.transparent) {
            int b = color.blue;
            int g = color.green;
            int r = color.red;
            final gray = (0.299 * b + 0.587 * g + 0.114 * r).round();
            color = gray >= avgGray ? Colors.white : Colors.black;

            if (color != Colors.black) {
              sum |= byteList[count];
            }
          }
          index++;
          count++;
        }
      }
      data.add(sum);
    } else if (bleBean.screenColorType == 3) {
      //全彩
      void addColor(int x, int y) {
        var color = getColor(x, y);
        color = ColorUtil.getColor(color);
        data
          ..add(color.red)
          ..add(color.green)
          ..add(color.blue);
      }

      for (int y = 0; y < screenSize.height.toInt(); y++) {
        for (int x = 0; x < screenSize.width.toInt(); x++) {
          addColor(x, y);
        }
      }
    }
    return data;
  }
}
